@file:Suppress("unused")

package com.hl.lib.utils.net

import android.text.TextUtils
import android.util.Log
import okhttp3.Call
import okhttp3.Callback
import okhttp3.ConnectionPool
import okhttp3.FormBody
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import java.io.IOException
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.util.concurrent.TimeUnit

/**
 * @author hyhdez
 * @des okhttp请求工具类
 * @date 2022/8/7 13:03
 */
object HttpUtil {
    private val TAG: String = HttpUtil::class.java.simpleName

    private val CLIENT: OkHttpClient = OkHttpClient.Builder()
        .retryOnConnectionFailure(false)
        .connectionPool(ConnectionPool(500, 20, TimeUnit.MINUTES))
        .connectTimeout(300, TimeUnit.SECONDS)
        .readTimeout(300, TimeUnit.SECONDS)
        .writeTimeout(300, TimeUnit.SECONDS)
        .build()

    /**
     * okHttp get方法的url拼接参数,并返回request对象
     *
     * @param url      url
     * @param paramMap map
     * @return request 对象
     */
    private fun getRequest(url: String, paramMap: Map<String, String> = mapOf()): Request {
        val urlBuilder = StringBuilder(url).append("?")
        if (paramMap.isNotEmpty()) {
            try {
                for (key in paramMap.keys) {
                    urlBuilder
                        .append(key)
                        .append("=")
                        .append(URLEncoder.encode(paramMap[key], "utf-8"))
                        .append("&")
                }
            } catch (e: UnsupportedEncodingException) {
                e.printStackTrace()
            }
        }
        val finalUrl = urlBuilder.substring(0, urlBuilder.length - 1)
        return Request.Builder()
            .url(finalUrl)
            .get()
            .build()
    }


    /**
     * okHttp get同步请求
     *
     * @param url      url
     * @param paramMap map
     * @return 返回的结果
     */
    suspend fun get(url: String, paramMap: Map<String, String> = mapOf()): String {
        val request = getRequest(url, paramMap)
        val response: Response?
        try {
            Log.e(TAG, "httpGet url = $url")
            response = CLIENT.newCall(request).execute()
            val responseBody = response.body
            if (responseBody == null) {
                Log.e(TAG, "httpGet 返回 responseBody = null")
                return ""
            }
            return responseBody.string()
        } catch (e: IOException) {
            e.printStackTrace()
            Log.e(TAG, "httpGet 请求失败: e = " + e.message)
        }
        return ""
    }

    /**
     * okHttp get异步请求
     *
     * @param url      url
     * @param paramMap map
     * @param callback 回调
     * @return
     */
    fun get(url: String, paramMap: Map<String, String> = mapOf(), callback: NetCallback) {
        val request = getRequest(url, paramMap)
        CLIENT.newCall(request).enqueue(LocalCallBack(callback))
    }

    /**
     * okHttp post返回request对象
     *
     * @param url  url
     * @param body body
     * @return request
     */
    private fun postRequest(url: String, body: RequestBody): Request {
        return Request.Builder()
            .url(url)
            .post(body)
            .build()
    }

    /**
     * okHttp post同步请求(json方式提交)
     *
     * @param url  url
     * @param json json
     * @return 结果
     */
    suspend fun httpJsonPost(url: String, json: String): String {
        if (TextUtils.isEmpty(url)) {
            Log.w(TAG, "url == null")
            return ""
        }
        val mediaType = "application/json; charset=utf-8".toMediaType()
        val body = json.toRequestBody(mediaType)
        val response: Response = CLIENT.newCall(postRequest(url, body)).execute()
        try {
            val responseBody = response.body
            if (responseBody == null) {
                Log.e(TAG, "httpJsonPost 返回 responseBody = null")
                return ""
            }
            return responseBody.string()
        } catch (e: IOException) {
            Log.e(TAG, "httpJsonPost e = " + e.message)
        }
        return ""
    }

    /**
     * okHttp post异步请求(json方式提交)
     *
     * @param url      url
     * @param json     json
     * @param callback callback
     */
    fun post(url: String, json: String, callback: NetCallback) {
        val mediaType = "application/json; charset=utf-8".toMediaType()
        val body = json.toRequestBody(mediaType)
        CLIENT.newCall(postRequest(url, body)).enqueue(LocalCallBack(callback))
    }


    /**
     * okHttp post同步请求(form方式提交)
     *
     * @param url      url
     * @param paramMap paramMap
     */
    suspend  fun formPost(url: String, paramMap: Map<String?, String?>): String? {
        if (TextUtils.isEmpty(url)) {
            Log.w(TAG, "url == null")
            return null
        }
        val builder: FormBody.Builder = FormBody.Builder()
        if (paramMap.isNotEmpty()) {
            for (key in paramMap.keys) {
                builder.add(key!!, paramMap[key]!!)
            }
        }
        val response: Response?
        try {
            response = CLIENT.newCall(postRequest(url, builder.build()))
                .execute()
            val responseBody = response.body
            if (responseBody == null) {
                Log.e(TAG, "httpFormPost 返回 responseBody = null")
                return ""
            }
            return responseBody.string()
        } catch (e: IOException) {
            Log.e(TAG, "httpFormPost e = " + e.message)
        }
        return null
    }

    /**
     * okHttp post异步请求(form方式提交)
     *
     * @param url      url
     * @param paramMap paramMap
     * @param callback callback
     */
    fun formPost(url: String, paramMap: Map<String?, String?>, callback: NetCallback) {
        if (TextUtils.isEmpty(url)) {
            Log.w(TAG, "httpFormPost url == null")
            return
        }
        val builder: FormBody.Builder = FormBody.Builder()
        if (paramMap.isNotEmpty()) {
            for (key in paramMap.keys) {
                builder.add(key!!, paramMap[key]!!)
            }
        }
        CLIENT.newCall(postRequest(url, builder.build()))
            .enqueue(LocalCallBack(callback))
    }

    /**
     * okHttp post同步请求(json方式提交)--附带Authorization认证
     *
     * @param url           url
     * @param json          json
     * @param authorization 授权
     * @return 结果
     */
    suspend fun authorizationPost(url: String, json: String, authorization: String): String {
        val mediaType = "application/json; charset=utf-8".toMediaType()
        val body = json.toRequestBody(mediaType)
        val response: Response?
        try {
            response = CLIENT.newCall(
                Request.Builder()
                    .url(url)
                    .header("authorization", authorization)
                    .post(body)
                    .build()
            ).execute()
            val responseBody = response.body
            if (responseBody == null) {
                Log.e(TAG, "httpJsonAuthorizationPost 返回 responseBody = null")
                return ""
            }
            return responseBody.string()
        } catch (e: IOException) {
            Log.e(TAG, "httpJsonAuthorizationPost e = " + e.message)
        }
        return ""
    }

    private class LocalCallBack(callback: NetCallback) : Callback {
        var mCallback: NetCallback? = callback

        override fun onFailure(call: Call, e: IOException) {
            mCallback?.onFail(-1, e.message)
        }

        @Throws(IOException::class)
        override fun onResponse(call: Call, response: Response) {
            mCallback?.let {
                val body = response.body ?: return
                mCallback!!.onSuccess(0, body.string())
            }
        }
    }
}
